module CoreLocalInterrupt(
  input clk,
  input rst,

  input wen,
  input ren,
  input [31:0] raddr,
  input [31:0] waddr,
  input [63:0] wdata,
  input [3:0] wsize,
  input [3:0] rsize,
  output reg [63:0] rdata,
  output reg rdata_valid,
  
  output tim_int_req,

  output mtip_clear,


  input msip_i,
  output msip_o,
  output msip_valid_o
);
  localparam BASE_ADDR = 32'h0200_0000;
  localparam MSIP_ADDR = BASE_ADDR+32'h0;
  localparam MTIMECMP_ADDR = BASE_ADDR+32'h4000;
  localparam MTIME_ADDR = BASE_ADDR+32'hBFF8;

  reg [63:0] mtimecmp,mtime;
  always @(posedge clk) begin
    if(rst) begin
      mtimecmp <= 64'b0;
      mtime <= 64'b0;
    end else begin
      mtime <= mtime + 64'b1;
      if(wen) 
        case(waddr)
        MTIMECMP_ADDR: mtimecmp <= wdata;
        MTIME_ADDR: mtime <= wdata;
        default:;
        endcase
    end
  end

  always @(posedge clk) begin
    if(rst) begin 
      rdata <= 64'b0;
      rdata_valid <= 1'b0;
    end else begin
      rdata_valid <= ren;
      if(ren)
        case(raddr)
        MSIP_ADDR: rdata <= {63'b0,msip_i};
        MTIMECMP_ADDR: rdata <= mtimecmp;
        MTIME_ADDR: rdata <= mtime;
        default: rdata <= 64'b0;
        endcase
      else 
        rdata <= 64'b0;
    end
  end


  assign mtip_clear = wen&(waddr==MTIMECMP_ADDR);
  assign msip_o = wdata[0];
  assign msip_valid_o = wen&(waddr==MSIP_ADDR);
  assign tim_int_req = mtime>=mtimecmp;
endmodule
